<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html><head><title>Programming in Lua : 15.4</title>
<link rel="stylesheet" type="text/css" href="pil.css">
</head>
<body>
<p class="warning">
<A HREF="contents.html"><IMG TITLE="Programming in Lua (first edition)" SRC="capa.jpg" ALT="" ALIGN="left"></A>This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.<BR>The third edition targets Lua 5.2 and is available at <A HREF="http://www.amazon.com/exec/obidos/ASIN/859037985X/theprogrammil3-20">Amazon</A> and other bookstores.<BR>By buying the book, you also help to <A HREF="../donations.html">support the Lua project</A>.
</p>
<table width="100%" class="nav">
<tr>
<td width="10%" align="left"><a href="15.3.html"><img border="0" src="left.png" alt="Previous"></a></td>
<td width="80%" align="center"><a href="contents.html"><font face="Helvetica,Arial,sanserif">
<font color="gray">Programming in </font><font color="blue"> Lua</font>
</font></a></td>
<td width="10%" align="right"><a href="15.5.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
<tr>
<td width="10%" align="left"></td>
<td width="80%" align="center"><a href="contents.html#P2">Part II. Tables and Objects</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="contents.html#15">Chapter 15. Packages</a></td>
<td width="10%" align="right"></td></tr>
</table>
<hr/>
<p><a name="package-env"><h2>15.4 &ndash; Using the Global Table</h2></a>

<p>One drawback of all these methods to create packages is
that they call for special attention from the programmer.
It is all too easy to forget a <b>local</b> in a declaration,
for instance.
Metamethods in the table of global variables offer some interesting
alternative techniques for creating packages.
The common part in all these techniques is the use of an
exclusive environment for the package.
This is easily done:
If we change the environment of the package's main chunk,
all functions it creates will share this new environment.

<p>The simplest technique does little more than that.
Once the package has an exclusive environment,
not only all its functions share this table,
but also all its global variables go to this table.
Therefore, we can declare all public functions as global variables
and they will go to a separate table automatically.
All the package has to do is to register this table as
the package name.
The next code fragment illustrates this technique for
the <code>complex</code> library:
<pre>
    local P = {}
    complex = P
    setfenv(1, P)
</pre>
Now, when we declare function <code>add</code>,
it goes to <code>complex.add</code>:
<pre>
    function add (c1, c2)
      return new(c1.r + c2.r, c1.i + c2.i)
    end
</pre>
Moreover, we can call other functions from
this package without any prefix.
For instance, <code>add</code> gets <code>new</code> from its environment,
that is, it gets <code>complex.new</code>.

<p>This method offers a good support for packages,
with little extra work on the programmer.
It needs no prefixes at all.
There is no difference between calling an exported and
a private function.
If the programmer forgets a <code>local</code>,
she does not pollute the global namespace;
instead, only a private function becomes public.
Moreover, we can use it together with the techniques from
the previous section for package names:
<pre>
    local P = {}   -- package
    if _REQUIREDNAME == nil then
      complex = P
    else
      _G[_REQUIREDNAME] = P
    end
    setfenv(1, P)
</pre>

<p>What is missing, of course, is access to other packages.
Once we make the empty table <code>P</code> our environment,
we lose access to all previous global variables.
There are several solutions to this,
each with its pros and cons.

<p>The simplest solution is inheritance,
as we saw earlier:
<pre>
    local P = {}   -- package
    setmetatable(P, {__index = _G})
    setfenv(1, P)
</pre>
(You must call <code>setmetatable</code> before
calling <code>setfenv</code>; can you tell why?)
With this construction,
the package has direct access to any global identifier,
but it pays a small overhead for each access.
A funny consequence of this solution is that,
conceptually, your package now contains all global variables.
For instance, someone using your package may call the standard
sine function writing <code>complex.math.sin(x)</code>.
(Perl's package system has this peculiarity, too.)

<p>Another quick method of accessing other packages
is to declare a local that holds the old environment:
<pre>
    local P = {}
    pack = P
    local _G = _G
    setfenv(1, P)
</pre>
Now you must prefix any access to external names with <code>_G.</code>,
but you get faster access, because there is no metamethod involved.
Unlike inheritance,
this method gives you write access to the old environment;
whether this is good or bad is debatable,
but sometimes you may need this flexibility.

<p>A more disciplined approach is to declare as locals only
the functions you need,
or at most the packages you need:
<pre>
    local P = {}
    pack = P
    
    -- Import Section:
    -- declare everything this package needs from outside
    local sqrt = math.sqrt
    local io = io
    
    -- no more external access after this point
    setfenv(1, P)
</pre>
This technique demands more work,
but it documents your package dependencies better.
It also results in faster code than the previous schemes.

<hr/>
<table width="100%" class="nav">
<tr valign="top">
<td width="90%" align="left">
<small>
  Copyright &copy; 2003&ndash;2004 Roberto Ierusalimschy.  All rights reserved.
</small>
</td>
<td width="10%" align="right"><a href="15.5.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
</table>


</body></html>

